Removing an old, cherished, yet pointless caveat "This documentation is
[supercollider.git] / Help / Streams-Patterns-Events / A Practical Guide / PG_Cookbook05_Using_Samples.html
blob18ebdb62d75f537cd46cf6c7ecce19f955194ee8
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5 <meta http-equiv="Content-Style-Type" content="text/css">
6 <title></title>
7 <meta name="Generator" content="Cocoa HTML Writer">
8 <meta name="CocoaVersion" content="1038.25">
9 <style type="text/css">
10 p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica}
11 p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
12 p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica}
13 p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
14 p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}
15 p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #606060}
16 p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}
17 p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #bf0000}
18 p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #0000bf}
19 p.p10 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #007300}
20 p.p11 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #0000ee}
21 span.s1 {color: #0000bf}
22 span.s2 {color: #000000}
23 span.s3 {color: #007300}
24 span.s4 {text-decoration: underline ; color: #0000bf}
25 span.s5 {font: 12.0px Helvetica}
26 span.Apple-tab-span {white-space:pre}
27 </style>
28 </head>
29 <body>
30 <p class="p1"><b>Using samples</b></p>
31 <p class="p2"><br></p>
32 <p class="p3"><b>Playing a pattern in time with a sampled loop</b></p>
33 <p class="p2"><br></p>
34 <p class="p4">A deceptively complex requirement... here, we will loop the a11wlk01.wav sample between 0.404561 and 3.185917 seconds (chosen for its surprisingly accurate four-beat groove), and overlay synthesized bells emphasizing the meter.</p>
35 <p class="p2"><br></p>
36 <p class="p4">It might be tempting to loop a <a href="../../UGens/Playback and Recording/PlayBuf.html"><span class="s1">PlayBuf</span></a> so that the loop runs automatically on the server, but it can easily drift out of sync with the client (because of slight deviations in the actual sample rate). Instead, the example defines a SynthDef that plays exactly one repetition of the loop, and repeatedly triggers it once per bar.</p>
37 <p class="p2"><br></p>
38 <p class="p4">The primary bell pattern accents the downbeat and follows with a randomly generated rhythm. The catch is that we have no assurance that the <a href="../Patterns/Pwrand.html"><span class="s1">Pwrand</span></a> \dur pattern will add up to exactly 4 beats. The <a href="../Patterns/Pfindur.html"><span class="s1">Pfindur</span></a> ("finite duration") pattern cuts off the inner Pbind after 4 beats. This would stop the pattern, except <a href="../Patterns/Pn.html"><span class="s1">Pn</span></a> repeats the Pfindur infinitely, placing the accent in the right place every time.</p>
39 <p class="p2"><br></p>
40 <p class="p4">The loop actually starts with a half-beat anacrusis, so <a href="../Patterns/Ptpar.html"><span class="s1">Ptpar</span></a> delays the bell patterns by 0.5 beats.</p>
41 <p class="p2"><br></p>
42 <p class="p5">(</p>
43 <p class="p6"><span class="s2">b = </span><span class="s1">Buffer</span><span class="s2">.read(s, </span>"sounds/a11wlk01.wav"<span class="s2">);</span></p>
44 <p class="p7"><br></p>
45 <p class="p8">// one loop segment</p>
46 <p class="p9">SynthDef<span class="s2">(</span><span class="s3">\oneLoop</span><span class="s2">, { </span>|out, bufnum, start, time, amp|</p>
47 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">var</span><span class="Apple-tab-span"> </span>sig = <span class="s1">PlayBuf</span>.ar(1, bufnum, startPos: start, loop: 0),</p>
48 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>env = <span class="s1">EnvGen</span>.kr(<span class="s1">Env</span>.linen(0.01, time, 0.05, level: amp), doneAction: 2);</p>
49 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">Out</span>.ar(out, (sig * env) ! 2)</p>
50 <p class="p5">}).add;</p>
51 <p class="p7"><br></p>
52 <p class="p9">SynthDef<span class="s2">(</span><span class="s3">\bell</span><span class="s2">, { </span>|out, accent = 0, amp = 0.1, decayScale = 1|</p>
53 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">var</span><span class="Apple-tab-span"> </span>exc = <span class="s1">PinkNoise</span>.ar(amp)</p>
54 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>* <span class="s1">Decay2</span>.kr(<span class="s1">Impulse</span>.kr(0), 0.01, 0.05),</p>
55 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>sig = <span class="s1">Klank</span>.ar(`[</p>
56 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>{ <span class="s1">ExpRand</span>(400, 1600) } ! 4,</p>
57 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>1 ! 4,</p>
58 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>{ <span class="s1">ExpRand</span>(0.1, 0.4) } ! 4</p>
59 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>], exc, freqscale: accent + 1, decayscale: decayScale);</p>
60 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">DetectSilence</span>.ar(sig, doneAction: 2);</p>
61 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">Out</span>.ar(out, sig ! 2)</p>
62 <p class="p5">}).add;</p>
63 <p class="p5">)</p>
64 <p class="p7"><br></p>
65 <p class="p5">(</p>
66 <p class="p5"><span class="s1">TempoClock</span>.default.tempo = 0.35953685899971 * 4;</p>
67 <p class="p7"><br></p>
68 <p class="p5">p = <span class="s1">Ptpar</span>([</p>
69 <p class="p5"><span class="Apple-tab-span"> </span>0, <span class="s1">Pbind</span>(</p>
70 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>\instrument<span class="s2">, </span>\oneLoop<span class="s2">,</span></p>
71 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>\bufnum<span class="s2">, b,</span></p>
72 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\amp</span>, 0.4,</p>
73 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\start</span>, 17841,</p>
74 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\time</span>, 0.35953685899971.reciprocal,</p>
75 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\dur</span>, 4</p>
76 <p class="p5"><span class="Apple-tab-span"> </span>),</p>
77 <p class="p5"><span class="Apple-tab-span"> </span>0.5, <span class="s1">Pn</span>(</p>
78 <p class="p9"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>Pfindur<span class="s2">(4,</span></p>
79 <p class="p9"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>Pbind<span class="s2">(</span></p>
80 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>\instrument<span class="s2">, </span>\bell<span class="s2">,</span></p>
81 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\accent</span>, <span class="s1">Pseq</span>([2, <span class="s1">Pn</span>(0, <span class="s1">inf</span>)], 1),</p>
82 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\amp</span>, <span class="s1">Pseq</span>([0.3, <span class="s1">Pn</span>(0.1, <span class="s1">inf</span>)], 1),</p>
83 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\decayScale</span>, <span class="s1">Pseq</span>([6, <span class="s1">Pn</span>(1, <span class="s1">inf</span>)], 1),</p>
84 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\dur</span>, <span class="s1">Pwrand</span>(#[0.25, 0.5, 0.75, 1], #[2, 3, 1, 1].normalizeSum, <span class="s1">inf</span>)</p>
85 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>)</p>
86 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>),<span class="Apple-converted-space"> </span></p>
87 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">inf</span>),</p>
88 <p class="p5"><span class="Apple-tab-span"> </span>0.5, <span class="s1">Pbind</span>(</p>
89 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>\instrument<span class="s2">, </span>\bell<span class="s2">,</span></p>
90 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\accent</span>, -0.6,</p>
91 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\amp</span>, 0.2,</p>
92 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>\decayScale<span class="s2">, 0.1,</span></p>
93 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\dur</span>, 1</p>
94 <p class="p5"><span class="Apple-tab-span"> </span>)</p>
95 <p class="p5">], 1).play;</p>
96 <p class="p5">)</p>
97 <p class="p7"><br></p>
98 <p class="p5">p.stop;</p>
99 <p class="p2"><br></p>
100 <p class="p4">The use of Ptpar above means that you could stop or start only the whole ball of wax at once, with no control over the three layers. It's no more difficult to play the layers in the independent event stream players, using the quant argument to ensure the proper synchronization. See the <a href="../../Scheduling/Quant.html"><span class="s1">Quant</span></a> help file for details on specifying the onset time of a pattern.</p>
101 <p class="p2"><br></p>
102 <p class="p5">(</p>
103 <p class="p5"><span class="s1">TempoClock</span>.default.tempo = 0.35953685899971 * 4;</p>
104 <p class="p7"><br></p>
105 <p class="p5">p = <span class="s1">Pbind</span>(</p>
106 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span></span>\instrument<span class="s2">, </span>\oneLoop<span class="s2">,</span></p>
107 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span></span>\bufnum<span class="s2">, b,</span></p>
108 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\amp</span>, 0.4,</p>
109 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\start</span>, 17841,</p>
110 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\time</span>, 0.35953685899971.reciprocal,</p>
111 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\dur</span>, 4</p>
112 <p class="p5">).play(quant: [4, 3.5]);</p>
113 <p class="p7"><br></p>
114 <p class="p5">q = <span class="s1">Pn</span>(</p>
115 <p class="p9"><span class="s2"><span class="Apple-tab-span"> </span></span>Pfindur<span class="s2">(4,</span></p>
116 <p class="p9"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>Pbind<span class="s2">(</span></p>
117 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>\instrument<span class="s2">, </span>\bell<span class="s2">,</span></p>
118 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\accent</span>, <span class="s1">Pseq</span>([2, <span class="s1">Pn</span>(0, <span class="s1">inf</span>)], 1),</p>
119 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\amp</span>, <span class="s1">Pseq</span>([0.3, <span class="s1">Pn</span>(0.1, <span class="s1">inf</span>)], 1),</p>
120 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\decayScale</span>, <span class="s1">Pseq</span>([6, <span class="s1">Pn</span>(1, <span class="s1">inf</span>)], 1),</p>
121 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s3">\dur</span>, <span class="s1">Pwrand</span>(#[0.25, 0.5, 0.75, 1], #[2, 3, 1, 1].normalizeSum, <span class="s1">inf</span>)</p>
122 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>)</p>
123 <p class="p5"><span class="Apple-tab-span"> </span>),<span class="Apple-converted-space"> </span></p>
124 <p class="p5"><span class="s1">inf</span>).play(quant: [4, 4]);</p>
125 <p class="p7"><br></p>
126 <p class="p5">r = <span class="s1">Pbind</span>(</p>
127 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span></span>\instrument<span class="s2">, </span>\bell<span class="s2">,</span></p>
128 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\accent</span>, -0.6,</p>
129 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\amp</span>, 0.2,</p>
130 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span></span>\decayScale<span class="s2">, 0.1,</span></p>
131 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\dur</span>, 1</p>
132 <p class="p5">).play(quant: [4, 4]);</p>
133 <p class="p5">)</p>
134 <p class="p7"><br></p>
135 <p class="p5">[p, q, r].do(<span class="s1">_</span>.stop);</p>
136 <p class="p7"><br></p>
137 <p class="p5">b.free;</p>
138 <p class="p2"><br></p>
139 <p class="p2"><br></p>
140 <p class="p3"><b>Using audio samples to play pitched material</b></p>
141 <p class="p2"><br></p>
142 <p class="p4">To use an instrument sample in a pattern, you need a SynthDef that plays the sample at a given rate. Here we will use <a href="../../UGens/Playback and Recording/PlayBuf.html"><span class="s1">PlayBuf</span></a>, which doesn't allow looping over a specific region. For that, <a href="../../UGens/Triggers/Phasor.html"><span class="s1">Phasor</span></a> and <a href="../../UGens/Oscillators/BufRd.html"><span class="s1">BufRd</span></a> are probably the best choice. (Third-party extension alert: LoopBuf by Lance Putnam is an alternative - click to download [osx]: <a href="http://www.uweb.ucsb.edu/~ljputnam/files/sc3/LoopBuf.zip"><span class="s4">http://www.uweb.ucsb.edu/~ljputnam/files/sc3/LoopBuf.zip</span></a>.)</p>
143 <p class="p2"><br></p>
144 <p class="p4">Frequency is controlled by the rate parameter. The sample plays at a given frequency at normal rate, so to play a specific frequency, <b>frequency / baseFrequency</b> gives you the required rate.</p>
145 <p class="p2"><br></p>
146 <p class="p4">The first example makes a custom protoEvent that calculates rate, as \freq, based on the base frequency. It uses one sample, so it would be best for patterns that will play in a narrow range. Since there isn't an instrument sample in the SuperCollider distribution, we will record a frequency-modulation sample into a buffer before running the pattern.</p>
147 <p class="p2"><br></p>
148 <p class="p8">// make a sound sample</p>
149 <p class="p5">(</p>
150 <p class="p5">var<span class="Apple-tab-span"> </span>recorder;</p>
151 <p class="p5">fork {</p>
152 <p class="p5"><span class="Apple-tab-span"> </span>b = <span class="s1">Buffer</span>.alloc(s, 44100 * 2, 1);</p>
153 <p class="p5"><span class="Apple-tab-span"> </span>s.sync;</p>
154 <p class="p5"><span class="Apple-tab-span"> </span>recorder = { <span class="s1">|freq = 440|</span></p>
155 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">var</span><span class="Apple-tab-span"> </span>initPulse = <span class="s1">Impulse</span>.kr(0),</p>
156 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>mod = <span class="s1">SinOsc</span>.ar(freq) * <span class="s1">Decay2</span>.kr(initPulse, 0.01, 3) * 5,</p>
157 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>car = <span class="s1">SinOsc</span>.ar(freq + (mod*freq)) * <span class="s1">Decay2</span>.kr(initPulse, 0.01, 2.0);</p>
158 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">RecordBuf</span>.ar(car, b, loop: 0, doneAction: 2);</p>
159 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>car ! 2</p>
160 <p class="p5"><span class="Apple-tab-span"> </span>}.play;</p>
161 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">OSCpathResponder</span>(s.addr, [<span class="s3">'/n_end'</span>, recorder.nodeID], { <span class="s1">|time, resp, msg|</span></p>
162 <p class="p6"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>"done recording"<span class="s2">.postln;</span></p>
163 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>resp.remove;</p>
164 <p class="p5"><span class="Apple-tab-span"> </span>}).add;<span class="Apple-tab-span"> </span></p>
165 <p class="p5">};</p>
166 <p class="p9">SynthDef<span class="s2">(</span><span class="s3">\sampler</span><span class="s2">, { </span>|out, bufnum, freq = 1, amp = 1|</p>
167 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">var</span><span class="Apple-tab-span"> </span>sig = <span class="s1">PlayBuf</span>.ar(1, bufnum, rate: freq, doneAction: 2) * amp;</p>
168 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">Out</span>.ar(out, sig ! 2)</p>
169 <p class="p5">}).add;</p>
170 <p class="p5">)</p>
171 <p class="p7"><br></p>
172 <p class="p5">(</p>
173 <p class="p8">// WAIT for "done recording" message before doing this</p>
174 <p class="p5"><span class="s1">var</span><span class="Apple-tab-span"> </span>samplerEvent = <span class="s1">Event</span>.default.put(<span class="s3">\freq</span>, { ~midinote.midicps / ~sampleBaseFreq });</p>
175 <p class="p7"><br></p>
176 <p class="p5"><span class="s1">TempoClock</span>.default.tempo = 1;</p>
177 <p class="p5">p = <span class="s1">Pbind</span>(</p>
178 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\degree</span>, <span class="s1">Pwhite</span>(0, 12, <span class="s1">inf</span>),</p>
179 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\dur</span>, <span class="s1">Pwrand</span>([0.25, <span class="s1">Pn</span>(0.125, 2)], #[0.8, 0.2], <span class="s1">inf</span>),</p>
180 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\amp</span>, <span class="s1">Pexprand</span>(0.1, 0.5, <span class="s1">inf</span>),</p>
181 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span></span>\sampleBaseFreq<span class="s2">, 440,</span></p>
182 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span></span>\instrument<span class="s2">, </span>\sampler<span class="s2">,</span></p>
183 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span></span>\bufnum<span class="s2">, b</span></p>
184 <p class="p5">).play(protoEvent: samplerEvent);</p>
185 <p class="p5">)</p>
186 <p class="p7"><br></p>
187 <p class="p5">p.stop;</p>
188 <p class="p5">b.free;</p>
189 <p class="p2"><br></p>
190 <p class="p2"><br></p>
191 <p class="p4"><b>Multi-sampled instruments</b></p>
192 <p class="p2"><br></p>
193 <p class="p4">To extend the sampler's range using multiple samples and ensure smooth transitions between frequency ranges, the SynthDef should crossfade between adjacent buffers. A hybrid approach is used here, where Pbind calculates the lower buffer number to use and the SynthDef calculates the crossfade strength. (The calculations could be structured differently, either putting more of them into the SynthDef for convenience in the pattern, or loading them into the pattern and keeping the SynthDef as lean as possible.)</p>
194 <p class="p2"><br></p>
195 <p class="p4">MIDI note numbers are used for these calculations because it's a linear frequency scale and linear interpolation is easier than the exponential interpolation that would be required when using Hz. Assuming a sorted array, indexInBetween gives the fractional index using linear interpolation. If you need to use frequency in Hz, use this function in place of indexInBetween.</p>
196 <p class="p2"><br></p>
197 <p class="p9"><span class="s2"><span class="Apple-tab-span"> </span>f = { </span>|val, array|</p>
198 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">var</span> a, b, div;</p>
199 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">var</span> i = array.indexOfGreaterThan(val);</p>
200 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>if(i.isNil) { array.size - 1 } {</p>
201 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>if(i == 0) { i } {</p>
202 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>a = array[i-1]; b = array[i];</p>
203 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>div = b / a;</p>
204 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>if(div == 1) { i } {</p>
205 <p class="p8"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// log() / log() == log(val/a) at base (b/a)</p>
206 <p class="p8"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// which is the inverse of exponential interpolation</p>
207 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>log(val / a) / log(div) + i - 1</p>
208 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>}</p>
209 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>}</p>
210 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>};</p>
211 <p class="p5"><span class="Apple-tab-span"> </span>};</p>
212 <p class="p2"><br></p>
213 <p class="p4">But that function isn't needed for this example:</p>
214 <p class="p2"><br></p>
215 <p class="p5">(</p>
216 <p class="p5"><span class="s1">var</span><span class="Apple-tab-span"> </span>bufCount;</p>
217 <p class="p5">~midinotes = (39, 46 .. 88);</p>
218 <p class="p5">bufCount = ~midinotes.size;</p>
219 <p class="p7"><br></p>
220 <p class="p5">fork {</p>
221 <p class="p8"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// record the samples at different frequencies</p>
222 <p class="p5"><span class="Apple-tab-span"> </span>b = <span class="s1">Buffer</span>.allocConsecutive(~midinotes.size, s, 44100 * 2, 1);</p>
223 <p class="p9"><span class="s2"><span class="Apple-tab-span"> </span></span>SynthDef<span class="s2">(</span><span class="s3">\sampleSource</span><span class="s2">, { </span>|freq = 440, bufnum|</p>
224 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">var</span><span class="Apple-tab-span"> </span>initPulse = <span class="s1">Impulse</span>.kr(0),</p>
225 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>mod = <span class="s1">SinOsc</span>.ar(freq) * <span class="s1">Decay2</span>.kr(initPulse, 0.01, 3) * 5,</p>
226 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>car = <span class="s1">SinOsc</span>.ar(freq + (mod*freq)) * <span class="s1">Decay2</span>.kr(initPulse, 0.01, 2.0);</p>
227 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">RecordBuf</span>.ar(car, bufnum, loop: 0, doneAction: 2);</p>
228 <p class="p5"><span class="Apple-tab-span"> </span>}).send(s);</p>
229 <p class="p5"><span class="Apple-tab-span"> </span>s.sync;</p>
230 <p class="p8"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// record all 8 buffers concurrently</p>
231 <p class="p5"><span class="Apple-tab-span"> </span>b.do({ <span class="s1">|buf, i|</span></p>
232 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s1">Synth</span>(<span class="s3">\sampleSource</span>, [freq: ~midinotes[i].midicps, bufnum: buf]);</p>
233 <p class="p5"><span class="Apple-tab-span"> </span>});</p>
234 <p class="p5">};</p>
235 <p class="p9">OSCresponderNode<span class="s2">(s.addr, </span><span class="s3">'/n_end'</span><span class="s2">, { </span>|t, r, m|</p>
236 <p class="p5"><span class="Apple-tab-span"> </span>bufCount = bufCount - 1;</p>
237 <p class="p5"><span class="Apple-tab-span"> </span>if(bufCount == 0) {</p>
238 <p class="p6"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>"done recording"<span class="s2">.postln;</span></p>
239 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>r.remove;</p>
240 <p class="p5"><span class="Apple-tab-span"> </span>};</p>
241 <p class="p5">}).add;</p>
242 <p class="p7"><br></p>
243 <p class="p9">SynthDef<span class="s2">(</span><span class="s3">\multiSampler</span><span class="s2">, { </span>|out, bufnum, bufBase, baseFreqBuf, freq = 440, amp = 1|</p>
244 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">var</span><span class="Apple-tab-span"> </span>buf1 = bufnum.floor,</p>
245 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>buf2 = buf1 + 1,</p>
246 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>xfade = (bufnum - buf1).madd(2, -1),</p>
247 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>basefreqs = <span class="s1">Index</span>.kr(baseFreqBuf, [buf1, buf2]),</p>
248 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>playbufs = <span class="s1">PlayBuf</span>.ar(1, bufBase + [buf1, buf2], freq / basefreqs, loop: 0, doneAction: 2),</p>
249 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>sig = <span class="s1">XFade2</span>.ar(playbufs[0], playbufs[1], xfade, amp);</p>
250 <p class="p5"><span class="Apple-tab-span"> </span><span class="s1">Out</span>.ar(out, sig ! 2)</p>
251 <p class="p5">}).add;</p>
252 <p class="p7"><br></p>
253 <p class="p5">~baseBuf = <span class="s1">Buffer</span>.alloc(s, ~midinotes.size, 1, { <span class="s1">|buf|</span> buf.setnMsg(0, ~midinotes.midicps) });</p>
254 <p class="p5">)</p>
255 <p class="p7"><br></p>
256 <p class="p5">(</p>
257 <p class="p5"><span class="s1">TempoClock</span>.default.tempo = 1;</p>
258 <p class="p5">p = <span class="s1">Pbind</span>(</p>
259 <p class="p10"><span class="s2"><span class="Apple-tab-span"> </span></span>\instrument<span class="s2">, </span>\multiSampler<span class="s2">,</span></p>
260 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\bufBase</span>, b.first,</p>
261 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\baseFreqBuf</span>, ~baseBuf,</p>
262 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\degree</span>, <span class="s1">Pseries</span>(0, <span class="s1">Prand</span>(#[-2, -1, 1, 2], <span class="s1">inf</span>), <span class="s1">inf</span>).fold(-11, 11),</p>
263 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\dur</span>, <span class="s1">Pwrand</span>([0.25, <span class="s1">Pn</span>(0.125, 2)], #[0.8, 0.2], <span class="s1">inf</span>),</p>
264 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\amp</span>, <span class="s1">Pexprand</span>(0.1, 0.5, <span class="s1">inf</span>),</p>
265 <p class="p8"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// some important conversions</p>
266 <p class="p8"><span class="s2"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span>// identify the buffer numbers to read</p>
267 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\freq</span>, <span class="s1">Pfunc</span> { <span class="s1">|ev|</span> ev.use(ev[<span class="s3">\freq</span>]) },</p>
268 <p class="p5"><span class="Apple-tab-span"> </span><span class="s3">\bufnum</span>, <span class="s1">Pfunc</span>({ <span class="s1">|ev|</span> ~midinotes.indexInBetween(ev[<span class="s3">\freq</span>].cpsmidi) })</p>
269 <p class="p5"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span>.clip(0, ~midinotes.size - 1.001)</p>
270 <p class="p5">).play;</p>
271 <p class="p5">)</p>
272 <p class="p7"><br></p>
273 <p class="p5">p.stop;</p>
274 <p class="p5">b.do(<span class="s1">_</span>.free); ~baseBuf.free;</p>
275 <p class="p2"><br></p>
276 <p class="p2"><br></p>
277 <p class="p11"><span class="s2">Previous:<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><a href="PG_Cookbook04_Sending_MIDI.html"><span class="s5">PG_Cookbook04_Sending_MIDI</span></a></span></p>
278 <p class="p11"><span class="s2">Next:<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><a href="PG_Cookbook06_Phrase_Network.html"><span class="s5">PG_Cookbook06_Phrase_Network</span></a></span></p>
279 </body>
280 </html>